/**
 *  fairy 版权所有 Copyright@2016年2月22日
 */
package com.fairy.sso.aspect;

import java.lang.reflect.Method;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.fairy.sso.annotation.FairyBizExceptionLog;
import com.fairy.sso.exception.SSOException;


/**
 * [FairyBizAspect.java]
 *
 * @ProjectName: [dubbo_fairy_common]
 * @Author: [waysun]
 * @CreateDate: [2016年2月22日 下午4:48:18]
 * @Update: [说明本次修改内容] BY [waysun] [2016年2月22日 下午4:48:18]
 * @Version: [v1.0]
 */
@Component
@Aspect
public class FairyBizAspect {
	private Logger log = Logger.getLogger(FairyBizAspect.class);

	private String des="";
	private String cls="";
	//private Param param=null;
	
	@Pointcut("@annotation(com.fairy.sso.annotation.FairyBizExceptionLog)")    
	public void pointCut() {
	}

	@After("pointCut()")
	public void after(JoinPoint joinPoint) {
		//System.out.println("after aspect executed");
	}

	@Before("pointCut()")
	public void before(JoinPoint joinPoint) {
		try {
			des="dubbo biz "+getBizMthodDescription(joinPoint);
			cls= "class:"+joinPoint.getTarget().getClass().getName()+",method:"+joinPoint.getSignature().getName();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		/**
		//如果需要这里可以取出参数进行处理
		Object[] args = joinPoint.getArgs();
        if (args != null && args.length > 0 ) {
        	for ( Object obj:args)
        	{
        		
        		
        	}
        }	
        */
	}

	@AfterReturning(pointcut = "pointCut()", returning = "returnVal")
	public void afterReturning(JoinPoint joinPoint, Object returnVal) {
		
		log.info(des+","+cls+",afterReturning executed, return result is "+ returnVal);
	}

	@Around("pointCut()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		//System.out.println("around start..");
		Object obj=null; 
		try {
			obj=pjp.proceed();

		} catch (Throwable ex) {
			//String des=getBizMthodDescription(pjp);
			log.info(des+",异常类:{"+pjp.getTarget().getClass().getName()+"}异常方法:{"+ pjp.getSignature().getName()+"}异常信息:{"+ex.getCause().getMessage()+"}");    
			log.info("<<<<<<<====================================================================================================================>>>>>>>");
			log.info(ex);
			throw new SSOException(des+","+ex.getCause().getMessage());
		}
		log.info(des+","+cls+",around end");
		return obj;
	}

	@AfterThrowing(pointcut = "pointCut()", throwing = "error")
	public void afterThrowing(JoinPoint jp, Throwable error) {

		try {
			log.info(getBizMthodDescription(jp)+","+error.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			throw new SSOException(e.getLocalizedMessage());
		}
	}
	
    
    /**  
     * 获取注解中对方法的描述信息 用于service层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     @SuppressWarnings("rawtypes")
	public  static String getBizMthodDescription(JoinPoint joinPoint)    
             throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
        String str="";
         for (Method method : methods) 
         {    
             if (method.getName().equals(methodName)) 
             {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) 
                 {    
                    description = method.getAnnotation(FairyBizExceptionLog.class).description();    

                    str=description;
                    break;    
                }    
            }    
        }  
         
        return str;    
    }
}



